/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.common.config;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
import yhao.infra.common.cache.YhaoCache;
import yhao.infra.common.cache.CacheOpeType;
import yhao.infra.common.cache.local.LocalCacheImpl;
import yhao.infra.common.cache.redis.RedisCacheImpl;

import java.util.HashMap;
import java.util.Map;

import static yhao.infra.common.ConfigFactory.*;

/**
 * 架构默认的缓存配置类
 *
 * @author yoara
 */
public class RedisConfig {
    @ConditionalOnProperty(value = BASIC_REDIS_ON,havingValue = "true",matchIfMissing = true)
    @ConditionalOnClass(redis.clients.jedis.Jedis.class)
    @Configuration
    static class EnableRedis{
        @Autowired
        private Environment env;

        @Bean(name = COMMON_CACHE_BEAN_NAME)
        public YhaoCache redisCache(RedisTemplate redisTemplate, RedisTemplate redisTemplateQuery) {
            Map<String, RedisTemplate<String, Object>> redisMap = new HashMap<>();
            redisMap.put(CacheOpeType.SAVE.name(), redisTemplate);
            redisMap.put(CacheOpeType.QUERY.name(), redisTemplateQuery);

            YhaoCache redisCache = new RedisCacheImpl(redisMap);
            String appName = env.getProperty(BASIC_REDIS_APP_NAME);
            if(!StringUtils.isEmpty(appName)){
                redisCache.setSystemUnique(appName.toUpperCase());
            }
            return redisCache;
        }

        @Bean(name = "redisTemplate")
        public RedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
            return makeRedisTemplate(jedisConnectionFactory);
        }

        @Bean(name = "redisTemplateQuery")
        public RedisTemplate redisTemplateQuery(JedisConnectionFactory jedisConnectionFactoryQuery) {
            return makeRedisTemplate(jedisConnectionFactoryQuery);
        }

        @Bean(name = "stringRedisTemplate")
        public StringRedisTemplate stringRedisTemplate(JedisConnectionFactory jedisConnectionFactory) {
            StringRedisTemplate redisTemplate = new StringRedisTemplate();
            redisTemplate.setConnectionFactory(jedisConnectionFactory);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            return redisTemplate;
        }

        @Bean(name = "jedisConnectionFactory")
        public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
            JedisConnectionFactory factory = makeJedisConnectionFactory(env,
                    BASIC_REDIS_SAVE_URL, BASIC_REDIS_SAVE_PORT,BASIC_REDIS_SAVE_PASSWORD,jedisPoolConfig);
            return factory;
        }

        @Bean(name = "jedisConnectionFactoryQuery")
        public JedisConnectionFactory jedisConnectionFactoryQuery(JedisPoolConfig jedisPoolConfig) {
            JedisConnectionFactory queryFactory = makeJedisConnectionFactory(env,
                    BASIC_REDIS_QUERY_URL, BASIC_REDIS_QUERY_PORT,BASIC_REDIS_QUERY_PASSWORD,jedisPoolConfig);
            return queryFactory;
        }

        @Bean(name = "jedisPoolConfig")
        public JedisPoolConfig jedisPoolConfig() {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(Integer.parseInt(env.getProperty(BASIC_REDIS_POOL_MAXTOTAL,"100")));
            config.setMaxIdle(Integer.parseInt(env.getProperty(BASIC_REDIS_POOL_MAXIDLE,"5")));
            config.setMaxWaitMillis(Integer.parseInt(env.getProperty(BASIC_REDIS_POOL_MAXWAITMILLIS,"20000")));
            return config;
        }
    }

    @ConditionalOnProperty(value = BASIC_REDIS_ON,havingValue = "false")
    @Configuration
    static class EnableLocalRedis{
        @Autowired
        private Environment env;

        @Bean(name = COMMON_CACHE_BEAN_NAME)
        public YhaoCache localCache() {
            YhaoCache localCache = new LocalCacheImpl();
            String appName = env.getProperty(BASIC_REDIS_APP_NAME);
            if(!StringUtils.isEmpty(appName)){
                localCache.setSystemUnique(appName.toUpperCase());
            }
            return localCache;
        }
    }
}
